{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "4b6c57ce",
   "metadata": {},
   "source": [
    "1. 泛型约束  \n",
    "    - 让泛型的类型有一定限制  \n",
    "    - 泛型约束一共有 6 种：  \n",
    "        1. **值类型**（`where T : struct`）  \n",
    "        2. **引用类型**（`where T : class`）  \n",
    "        3. **存在无参公共构造函数**（`where T : new()`）  \n",
    "        4. **某个类本身或者其派生类**（`where T : 某类`）  \n",
    "        5. **实现某个接口**（`where T : 某接口`）  \n",
    "        6. **另一个泛型类型本身或者其派生类型**（`where T : U`）  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "c06430c5",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "42\r\n"
     ]
    }
   ],
   "source": [
    "// 值类型\n",
    "class TestClassWithMethod<T> where T:struct{\n",
    "    public T value;\n",
    "\n",
    "    public void TestFunc<K>()where K:struct{\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<int> testClass = new TestClassWithMethod<int>();\n",
    "testClass.value = 42;\n",
    "testClass.TestFunc<int>();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "55e85fae",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Generics!\r\n"
     ]
    }
   ],
   "source": [
    "//引用类型\n",
    "class TestClassWithMethod<T> where T:class{\n",
    "    public T value;\n",
    "\n",
    "    public void TestFunc<K>()where K:class{\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<string> testClass = new TestClassWithMethod<string>();\n",
    "testClass.value = \"Hello, Generics!\";\n",
    "testClass.TestFunc<string>();\n",
    "\n",
    "//报错\n",
    "//TestClassWithMethod<int> testClass2 = new TestClassWithMethod<int>();\n",
    "//testClass2.value = 42;\n",
    "//testClass2.TestFunc<int>();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "617f79fe",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test\n",
      "Submission#27+Test\n"
     ]
    }
   ],
   "source": [
    "//公共无参构造约束\n",
    "class TestClassWithMethod<T> where T:new(){\n",
    "    public T value;\n",
    "\n",
    "    public void TestFunc<K>()where K:new(){\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "class Test{\n",
    "    //必须有公共的无参构造函数(非抽象)\n",
    "    public Test(){\n",
    "        Console.WriteLine(\"Test\");\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<Test> testClass = new TestClassWithMethod<Test>();\n",
    "testClass.value = new Test();\n",
    "testClass.TestFunc<Test>();\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "9b3dc109",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Test\n",
      "Submission#27+Test\n",
      "Test\n",
      "TestChild\n",
      "Submission#28+TestChild\n"
     ]
    }
   ],
   "source": [
    "// 某个类及其派生类\n",
    "class TestClassWithMethod<T> where T:Test{\n",
    "    public T value;\n",
    "\n",
    "    public void TestFunc<K>()where K:Test{\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "class TestChild:Test{\n",
    "    public TestChild(){\n",
    "        Console.WriteLine(\"TestChild\");\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<Test> testClass = new TestClassWithMethod<Test>();\n",
    "testClass.value = new Test();\n",
    "testClass.TestFunc<Test>();\n",
    "\n",
    "TestClassWithMethod<TestChild> testClassChild = new TestClassWithMethod<TestChild>();\n",
    "testClassChild.value = new TestChild();\n",
    "testClassChild.TestFunc<TestChild>();\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "018ffcfa",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Submission#18+Bird\n",
      "Submission#18+Bird\n"
     ]
    }
   ],
   "source": [
    "//接口约束,必须是接口和接口的派生类或接口\n",
    "interface IFly{\n",
    "}\n",
    "class Bird:IFly{\n",
    "}\n",
    "class TestClassWithMethod<T> where T:IFly{\n",
    "    public T value;\n",
    "\n",
    "    public void TestFunc<K>()where K:IFly{\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<Bird> testClass = new TestClassWithMethod<Bird>();\n",
    "testClass.value = new Bird();\n",
    "testClass.TestFunc<Bird>();\n",
    "\n",
    "TestClassWithMethod<IFly> testClass2 = new TestClassWithMethod<IFly>(); // 接口不能实例化,只能用子类赋值\n",
    "testClass2.value = new Bird();\n",
    "testClass2.TestFunc<IFly>();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "id": "03cc7a94",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "//另一个泛型约束\n",
    "class TestClassWithMethod<T,K>where T:K{ //T的类型是K或者是其派生类\n",
    "    public T value = default(T);\n",
    "\n",
    "    public void TestFunc<M,N>() where M:N{\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<string,object> testClass = new TestClassWithMethod<string,object>();"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd4e49b5",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "source": [
    "2. 约束的组合使用"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "e7816583",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "//泛型约束到存在无参构造函数的引用类型\n",
    "class TestClassWithMethod<T> where T:class ,new(){\n",
    "    public T value;\n",
    "\n",
    "    public void TestFunc(){\n",
    "        value = new T();\n",
    "    }\n",
    "}\n",
    "\n",
    "class Test{\n",
    "    public Test(){\n",
    "\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<Test> testClass = new TestClassWithMethod<Test>();"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "564656f2",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "source": [
    "3. 多个泛型有约束"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "id": "ca3f3dac",
   "metadata": {
    "language_info": {
     "name": "polyglot-notebook"
    },
    "polyglot_notebook": {
     "kernelName": "csharp"
    }
   },
   "outputs": [],
   "source": [
    "class TestClassWithMethod<T,K> where T:class,new() where K:struct{\n",
    "    public T value = default(T);\n",
    "    public K key = default(K);\n",
    "\n",
    "    public void TestFunc(){\n",
    "        value = new T();\n",
    "        Console.WriteLine(value);\n",
    "    }\n",
    "}\n",
    "class Test{\n",
    "    public Test(){\n",
    "\n",
    "    }\n",
    "}\n",
    "\n",
    "TestClassWithMethod<Test, int> testClass = new TestClassWithMethod<Test, int>();"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": ".NET (C#)",
   "language": "C#",
   "name": ".net-csharp"
  },
  "language_info": {
   "name": "polyglot-notebook"
  },
  "polyglot_notebook": {
   "kernelInfo": {
    "defaultKernelName": "csharp",
    "items": [
     {
      "aliases": [],
      "name": "csharp"
     }
    ]
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
